﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Media;
using ScrumTable.BL.DM.DataManagement;
using ScrumTable.Common.Collections;
using ScrumTable.UI.ViewModel.Data;
using ScrumTable.UI.ViewModel.Extension;

#endregion

namespace ScrumTable.UI.ViewModel
{
    /// <summary>
    /// User story for the View model
    /// </summary>
    public class MemberViewModel : ViewModelBase, IViewModelData<Member>
    {

        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------
        private static readonly Dictionary<string, SolidColorBrush> ColorsMember = new Dictionary<string, SolidColorBrush>();
        private static List<SerializablePair<string,string>> _userList = new List<SerializablePair<string, string>>();
        private readonly Member _member;
        private double _workEstimate;
        private double _workCompleted;
        private double _workRemaining;
        
        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------
        
        /// <summary>
        /// Gets the color for this member.
        /// </summary>
        /// <value>The color.</value>
        public Brush Color
        {
            get
            {
                if (Original == null) return Brushes.Transparent;
                
                if(!ColorsMember.ContainsKey(Original.Name))
                {
                    Random random = new Random(Original.Name.GetHashCode());
                    var brush = new SolidColorBrush(System.Windows.Media.Color.FromRgb((byte) random.Next(0, 255),
                                                                                       (byte) random.Next(0, 255),
                                                                                       (byte) random.Next(0, 255))) {Opacity = 0.8};
                    brush.Freeze();
                    ColorsMember.Add(Original.Name, brush);
                }
                return ColorsMember[Original.Name];
            }
            
        }

        public Color SetColor
        {
            set
            {
                var item = _userList.Find((x) => x.Left == Original.Name);
                if( item == null)
                {
                    _userList.Add( new SerializablePair<string, string>(Original.Name, value.ToString()));
                }
                else
                {
                    item.Right = value.ToString();    
                }
                var brush = new SolidColorBrush(value) { Opacity = 0.8 };
                brush.Freeze();
                ColorsMember[Original.Name] = brush;
                SendPropertyChanged("Color");
            }
        }

        /// <summary>
        /// Gets the original instance.
        /// </summary>
        /// <value></value>
        public Member Original { get { return _member; } }

        /// <summary>
        /// Gets the id of the member.
        /// </summary>
        public string Id
        {
            get { return _member.Id; }
        }

        /// <summary>
        /// Gets the name of the member.
        /// </summary>
        public string Name
        {
            get { return _member.Name; }
            set
            {
                _member.Name = value;
                SendPropertyChanged("Name");
             }
        }

        /// <summary>
        /// Gets the e-mail of the member.
        /// </summary>
        public string EMail
        {
            get { return _member.EMail; }
        }

        /// <summary>
        /// Gets the picture of the member.
        /// </summary>
        public Uri Picture
        {
            get
            {
                return _member.PictureUri;
            }
        }

        /// <summary>
        /// Returns true if the current user can be used to login.
        /// </summary>
        public bool CanLogIn
        {
            get { return (_member==null)?false:_member.CanLogIn; }
        }

        /// <summary>
        /// Gets the name of the parent of the task.
        /// </summary>
        public string Parent
        {
            get
            {
                if (_member.Parent == null)
                    return "...";
                return _member.Parent.Id;
            }
        }

        private Iteration _workForIteration;
        /// <summary>
        /// Gets or sets the iteration for which the Work is calculate.
        /// </summary>
        /// <value>The iteration.</value>
        public Iteration WorkForIteration
        {
            get
            {
                return _workForIteration;
            }
            set
            {
                _workForIteration = value;
                UpdateWorkData();
            }
        }

        /// <summary>
        /// Gets or sets the work estimate.
        /// </summary>
        /// <value>The work estimate.</value>
        public double WorkEstimate
        {
            get
            {
                return _workEstimate;
            }
            set
            {
                _workEstimate = value;
                SendPropertyChanged("WorkEstimate");
            }
        }
        /// <summary>
        /// Gets or sets the work completed.
        /// </summary>
        /// <value>The work completed.</value>
        public double WorkCompleted
        {
            get
            {
                return _workCompleted;
            }
            set
            {
                _workCompleted = value;
                SendPropertyChanged("WorkCompleted");
            }
        }
        /// <summary>
        /// Gets or sets the work remaining.
        /// </summary>
        /// <value>The work remaining.</value>
        public double WorkRemaining
        {
            get
            {
                return _workRemaining;
            }
            set
            {
                _workRemaining = value;
                SendPropertyChanged("WorkRemaining");
            }
        }


        /// <summary>
        /// Gets or sets the work capacity for this iteration.
        /// </summary>
        /// <value>The work capacity.</value>
        public double WorkCapacity { get; set; }

        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------
        /// <summary>
        /// Initializes a new instance of the <see cref="MemberViewModel"/> class.
        /// </summary>
        /// <param name="member">The member.</param>
        public MemberViewModel(Member member)
        {
            _member = member;
            if (_member != null)
            {
                _member.Context.ElementChanged += OnContextElementChanged;
                _member.Context.CollectionChanged += OnContextCollectionChanged;
            }


        }

       
        

        #endregion

        #region Overrides
        //--------------------------------------------------------------------
        // Overrides
        //--------------------------------------------------------------------

        /// <summary>
        /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
        /// <returns>
        /// 	<c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        /// <exception cref="T:System.NullReferenceException">
        /// The <paramref name="obj"/> parameter is null.
        /// </exception>
        public override bool Equals(object obj)
        {
            if (!(obj is MemberViewModel)) return false;
            return Equals(obj as MemberViewModel);
        }

        /// <summary>
        /// Equalses the specified other.
        /// </summary>
        /// <param name="other">The other.</param>
        /// <returns></returns>
        public bool Equals(MemberViewModel other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return other._member == _member;
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            return (_member != null ? _member.GetHashCode() : 0);
        }

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

         /// <summary>
        /// Releases managed (c# or .net) resources.
        /// </summary>
        protected override void ReleaseManagedResources()
         {
             if (Original != null)
             {
                 Original.Context.CollectionChanged -= OnContextCollectionChanged;
                 Original.Context.ElementChanged -= OnContextElementChanged;
             }
         }

        public static void SetInitColors(List<SerializablePair<string, string>> list)
        {
            
            _userList = list ?? new List<SerializablePair<string, string>>();
            ColorsMember.Clear();
            foreach (var colorPair in list)
            {
                var brush = new SolidColorBrush(ColorExtensions.ColorFromString(colorPair.Right)) { Opacity = 0.5 };
                brush.Freeze();
                ColorsMember[colorPair.Left] = brush;
            }
        }

        /// <summary>
        /// Updates the work data.
        /// </summary>
        private void UpdateWorkData()
        {
            if (WorkForIteration == null) return;

            var memberInfo = from x in WorkForIteration.Stories
                             from y in x.Tasks
                             where y.AssignedMember == Original
                             group y by y.AssignedMember into g
                             select new { Member = g.Key, WorkRemaining = g.Sum(y => y.RemainingWork), WorkEstimate = g.Sum(y => y.Estimate), WorkCompleted = g.Sum(y => y.CompletedWork) };

            if (memberInfo.Count() > 0)
            {
                var theMember = memberInfo.First();

                WorkCompleted = theMember.WorkCompleted.Value;
                WorkEstimate = theMember.WorkEstimate.Value;
                WorkRemaining = theMember.WorkRemaining.Value;
            }
            else
            {
                WorkCompleted = 0;
                WorkEstimate = 0;
                WorkRemaining = 0;
            }

            SendPropertyChanged("WorkEstimate");
            SendPropertyChanged("WorkCompleted");
            SendPropertyChanged("WorkRemaining");
        }
        
        /// <summary>
        /// Saves the Member
        /// </summary>
        public void Save()
        {
            Original.Save();
        }


        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------

        private void OnContextElementChanged(object sender, PropertyChangedEventArgs e)
        {
            //TODO performance?!
            if (e is DomainChangedEventArgs && ((DomainChangedEventArgs)e).ContainsPropertyNames("RemainingWork", "CompletedWork", "AssignedMember"))
            {
                UpdateWorkData();
            }
        }

        void OnContextCollectionChanged(object sender, DomainCollectionChangedEventArgs e)
        {
            UpdateWorkData();
        }

        #endregion
    }
}